這篇是在講React的測試,所以就拿個幾天篇幅來講hooks,React在v16.8之後開始支援hook,那就拿一些較常用的hook來介紹吧.
TL;DR
先來一段程式吧,這邊我就不講class component時期的state的設計,應該大家都會吧?XDD
import { useState } from 'react';
const [count, setCount] = useState(0)
簡單的敘述一下,useState(0)裡面的0是initial Value,他的型別可以是:
就如同我上面code所顯示的,state共有2種型別1種function可以設定,其中可以是primtive value or object以及callback可以設定,那我們設定完了值到哪了呢? 以範例為例就是[count, 忽略] ← 所以我們初始狀態0可以從count這個variable 取得,那我們如何更改count的值呢,這時候就可以用第二個setCount 這個setter來更改,但在講設定狀態之前,我們要講一下lazy state
大家想像一下如果初始化的值要運算很久怎辦
function caculate() {
....假裝一下 可能有幾百行
}
const App: FC = () => {
const [info, setHeavyInfo] = useState(caculate())
}
這樣寫你的網頁一定爆幹強很硬,因為你的網頁每次render都要跑幾百行initialize;
function caculate() {
....as above
}
const App: FC = () => {
const [info, setHeavyInfo] = useState(() => caculate());
}
如果這樣寫,只會initialize 一開始render那一次,接下來講到setCount的setter
function handleUpdateCount() {
setCount(prevCount => prevCount + 1);
} -> 這邊會牽扯到一個觀念 batch update
setter設定完之後整個component會re-render,當我們使用setState大家其實可以發現一件事情就是如果程式用以下的寫法:
function handleUpdateCount() {
setCount(count+1);
setCount(count+1);
setCount(count+1);
}
大家會發現,為...為什麼還是+1而已
"Currently (React 16 and earlier), only updates inside React event handlers are batched by default" , according to Dan Abramov.
因為在一個function同時執行setCount是會batching update的所以只會更新只會觸發一次render 所以是+1,如果要修正這個問題有兩個解決方案.
(1)啊第一個解法就是
function handleUpdateCount() {
setCount(prevCount => prevCount + 1);
setCount(prevCount => prevCount + 1);
setCount(prevCount => prevCount + 1);
}
執行時每次都會取得前一個的狀態
(2) useReducer大家自己去看官方文件
接下來無聊,如何自己寫一個useState
let state;
function render() {
ReactDOM.render(<App />, document.getElementById('root'));
}
function useState(initialState) {
state = state || initialState;
function setState(newState) {
state = newState;
render()
}
return [state, setState];
}
render()